﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Draco.OWF.Repository.Factory;

namespace Draco.OWF.Repository.Deserialize
{
    public class XmlDeserializeProvider
    {
        private XmlDocument m_xDoc;
        private IPackageHeader m_PackageHeader;
        private IProcess m_ProcessDefinitions = null;

        public XmlDeserializeProvider(XmlDocument xDoc)
        {
            if (xDoc == null)
                throw new ArgumentNullException();
            m_xDoc = xDoc;

            DeserializePackage();
        }
        /// <summary>
        /// 
        /// </summary>
        protected void DeserializePackage()
        {
            XmlElement Xmlpackage = m_xDoc.DocumentElement;
            m_PackageHeader = new PackageHeader();
            m_PackageHeader.Deserialize(Xmlpackage);

            XmlNode li = Xmlpackage.SelectSingleNode("WorkflowProcess");
            m_ProcessDefinitions = DeserializeWorkflowProcesses(li as XmlElement, m_PackageHeader);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="xmlProcess"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        protected IProcess DeserializeWorkflowProcesses(XmlElement xmlProcess,IPackageHeader header)
        {
            if (xmlProcess == null) return null;
            String type = xmlProcess.GetAttribute("Type");
            if (String.IsNullOrEmpty(type))
                type = DefaultTypes.DefaultProcessDefinitionType;
            else
                type = header.getRegistedType(type);

            //create object instance
            IProcess processDefinition = ObjectFactory.CreateObject(type) as IProcess;

            String name = xmlProcess.GetAttribute("Name");
            processDefinition.Name = name;

            String Id = xmlProcess.GetAttribute("Id");
            processDefinition.Id = Id;
            XmlElement xmlProcessHeader = xmlProcess.SelectSingleNode("ProcessHeader") as XmlElement;
            if (xmlProcessHeader != null)
            {
                XmlElement xmlDispalyName = xmlProcessHeader.SelectSingleNode("DisplayName") as XmlElement;
                if (xmlDispalyName != null)
                    processDefinition.DisplayName = xmlDispalyName.InnerText;

                XmlElement xmlDescription = xmlProcessHeader.SelectSingleNode("Description") as XmlElement;
                if (xmlDescription != null)
                    processDefinition.Description = xmlDescription.InnerText;

                XmlElement xmlAuthor = xmlProcessHeader.SelectSingleNode("Author") as XmlElement;
                if (xmlAuthor != null)
                    processDefinition.Creator = xmlAuthor.InnerText;

                XmlElement xmlCreatDate = xmlProcessHeader.SelectSingleNode("CreatDate") as XmlElement;
                if (xmlCreatDate != null)
                {
                    try
                    {
                        DateTime date = Convert.ToDateTime(xmlCreatDate.InnerText);
                        processDefinition.CreateDate = date;
                    }
                    catch { }
                }

                XmlElement xmlVersion = xmlProcessHeader.SelectSingleNode("Version") as XmlElement;
                if (xmlVersion != null)
                    processDefinition.Version = xmlVersion.InnerText;
            }

            //activities
            XmlElement xmlActivities = xmlProcess.SelectSingleNode("Activities") as XmlElement;
            if (xmlActivities != null)
            {
                XmlNodeList list = xmlActivities.SelectNodes("Activity");
                if (list != null && list.Count > 0)
                {
                    foreach (var li in list)
                    {
                        IActivity activity = DeserializeActivity(li as XmlElement, header);
                        if (activity != null)
                        {
                            processDefinition.AddActivity(activity);
                        }
                    }
                }
            }
            //routes
            XmlElement xmlRoutes = xmlProcess.SelectSingleNode("Transitions") as XmlElement;
            if (xmlRoutes != null)
            {
                XmlNodeList list = xmlRoutes.SelectNodes("Transition");
                if (list != null && list.Count > 0)
                {
                    foreach (var li in list)
                    {
                        IRoute route = DeserializeRoute(li as XmlElement, header);
                        if (route != null)
                        {
                            processDefinition.AddRoute(route);
                        }
                    }
                }
            }
            return processDefinition;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="xmlActivity"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        protected IActivity DeserializeActivity(XmlElement xmlActivity, IPackageHeader header)
        {
            if (xmlActivity == null) return null;
            String type = xmlActivity.GetAttribute("Type");
            String fullType = header.getRegistedType(type);
            if (String.IsNullOrEmpty(fullType))
                fullType = type;
            
            //create object instance
            IActivity activity = ObjectFactory.CreateObject(fullType) as IActivity;

            String name = xmlActivity.GetAttribute("Name");
            activity.Name = name;

            String Id = xmlActivity.GetAttribute("Id");
            activity.Id = Id;

            XmlElement xmlConfiguration = xmlActivity.SelectSingleNode("Configuration") as XmlElement;
            if (xmlConfiguration != null)
            {
                activity.DeserializeConfiguration(xmlConfiguration);
            }
            return activity;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="xmlRoute"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        protected IRoute DeserializeRoute(XmlElement xmlRoute, IPackageHeader header)
        {
            return null;
        }
    }
}
